package com.climbingGuide.java;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.markupartist.android.widget.ActionBar;
import com.markupartist.android.widget.ActionBar.AbstractAction;
import com.markupartist.android.widget.ActionBar.Action;
import com.markupartist.android.widget.ActionBar.IntentAction;

public class ClimbingGuideActivity extends MapActivity implements SensorEventListener{
	
	private static final int LAT_INIC = 28299221;
	private static final int LONG_INIC = -16525690;
	private static final int ZOOM_INIC = 11;

	private static final int MILISEC = 7000;
	private static final int METERS = 15;
	
	private BaseDatos bd;
	
	public MapView mapa;
	public ActionBar actionBar;
	
	private LocationManager locMgr; 
    private LocationListener onLocationChange;
    private Drawable iconMyPos;
	private int latActual;
	private int longActual;
	private boolean activadoGPS = true; 
	
	private SensorManager sensorMgr;
	private Sensor sensor;
	private boolean sensorActivo = false;
//----------------------- Overrides --------------------------------------	
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //-------- Base Datos -------------------------
        bd = new BaseDatos(this);
   	 	try {
			bd.crearBaseDatos();
			bd.abrirBD();
		} catch (IOException e) {
			e.printStackTrace();
			Log.d("Splash/BaseDatos", e.toString());
			finish();
		}
		
        //----------------- Action Bar inic
        actionBar = (ActionBar)findViewById(R.id.actionbar);
        //actionBar.setHomeLogo(android.R.drawable.ic_dialog_map);
        actionBar.setHomeAction(new ExampleAction(android.R.drawable.ic_menu_mapmode));
        //actionBar.addAction(new ExampleAction(android.R.drawable.ic_dialog_info));
        actionBar.setTitle("");
        actionBar.setOnTitleClickListener(new OnClickListener(){

			@Override
			public void onClick(View arg0) {
				TextView tv = (TextView)arg0;
				String cadena = tv.getText().toString().trim();
				if (!cadena.contentEquals("")){
					//Toast.makeText(ClimbingGuideActivity.this, tv.getText().toString(), Toast.LENGTH_SHORT).show();
					String[] cad = cadena.split("\\|");
					Intent intent = new Intent(ClimbingGuideActivity.this, InfoSector.class);
					intent.putExtra("sectorName", cad[0].trim());
					startActivity(intent);
				}
			}});
        final Action listaActivity = new IntentAction(this, new Intent(this, ListaSectores.class), android.R.drawable.ic_menu_myplaces);
        actionBar.addAction(listaActivity);
       //---------------------Map Inic
        mapa = (MapView)findViewById(R.id.MapView);
        mapa.setBuiltInZoomControls(true);
        mapa.setSatellite(true);
		GeoPoint puntoInic = new GeoPoint(LAT_INIC , LONG_INIC);
		MapController control = mapa.getController();
		control.setCenter(puntoInic);
        control.setZoom(ZOOM_INIC);
        cargarPuntosMapa (bd.getInfoMap(false, 
        		new String[] {"nombre", "inicX", "inicY", "finX", "finY", "numVias", "grados", "tipo", "gpx"}, 
        		null, null, null, null, null));
        iconMyPos = this.getResources().getDrawable(R.drawable.marker_04);
        inicLocation();
        inicOrientation();
    }
   
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	@Override
	public void onPause(){
		super.onPause();
		if (activadoGPS){
			locMgr.removeUpdates(onLocationChange);
			if (sensorActivo){
				sensorMgr.unregisterListener(this);
				sensorActivo = false;
			}
			borraUltimoOverlay();
		}
	}
	@Override 
	public void onResume(){
		super.onResume();
		if (activadoGPS) {
			activadoGPS = inicPosGPS();
			if (!sensorActivo && activadoGPS)
				sensorActivo = sensorMgr.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);	
		}
	}
	
	@Override
	public void onDestroy(){
		bd.close();
		super.onDestroy();
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		float angulo = event.values[0];	//eje azimutal
		borraUltimoOverlay();
		cargaPuntoGPS(latActual, longActual, angulo);
	}
//----------------------------Metodos ---------------------------------	
	private void inicOrientation(){
		sensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
		sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);
	}
	private boolean inicPosGPS(){
		latActual = LAT_INIC;
		longActual = LONG_INIC;
		//float direccion = 0;
		boolean result = false;
		if (locMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)){	//carga GPS_provider
			Location miLocation = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);			
			if (miLocation != null){
				latActual = (int)(miLocation.getLatitude() * 1E6);
				longActual = (int) (miLocation.getLongitude() *1E6);
				//direccion= miLocation.getBearing();
			}
			/*borraUltimoOverlay();
			cargaPuntoGPS(latActual,longActual, direccion);*/
			//Carga gps
			locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, MILISEC, METERS, onLocationChange);
        	result = true;
		}//carga network provider
		else if (locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
			Location miLocation = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);			
			if (miLocation != null){
				latActual = (int)(miLocation.getLatitude() * 1E6);
				longActual = (int)(miLocation.getLongitude() * 1E6);
				//direccion= miLocation.getBearing();
			}
			/*borraUltimoOverlay();
			cargaPuntoGPS(latActual,longActual, direccion);*/
			//Carga network_provider
			locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MILISEC, METERS, onLocationChange);
			result = true;
		}
		return result;
	}
	
	
	private void inicLocation(){
		locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		onLocationChange = new LocationListener(){			//listener

			@Override
			public void onLocationChanged(Location location) {
				if (location != null){
					//
					latActual = (int)(location.getLatitude() * 1E6);
					longActual = (int)(location.getLongitude() * 1E6);
					/*if (!sensorActivo){	//Si esta activo se carga en onSensorChanged
						borraUltimoOverlay();	//borramos el ultimo de la lista que corresponde al punto GPS
						cargaPuntoGPS(latActual, longActual);
					}*/
					Log.i("LocationActivity", "Received Location update.");
				}
			}

			@Override
			public void onProviderDisabled(String provider) {	
				
				Log.i("LocationActivity", "Location provider " + provider + " has been disabled.");
			}

			@Override
			public void onProviderEnabled(String provider) {
				Log.i("LocationActivity", "Location provider " + provider + " has been enabled.");
			}

			@Override
			public void onStatusChanged(String provider, int status, Bundle extras) {
				if ((provider.contentEquals(LocationManager.GPS_PROVIDER)) && (status > 0))	//TEMPORARILY_UNAVAILABLE 
					if (locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
							locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MILISEC, METERS, onLocationChange);
				if ((provider.contentEquals(LocationManager.GPS_PROVIDER)) && (status == 0))	//Available
					locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, MILISEC, METERS, onLocationChange);
				Log.i("LocationActivity", "Location provider " + provider + " has changed status to " + status);
			}
		};
		//activadoGPS = inicPosGPS();	//Cargamos capa GPS/Se inicializa en el onResume
	}
	
	private void cargaPuntoGPS(int lat, int lon, float grados){
		if (grados != 0){
			iconMyPos = rotateIcon(grados);
			//iconMyPos.setAlpha(190);	//nivel de transparencia
		}
		GeoPoint posAct = new GeoPoint(lat, lon);
		OverlayItem miPunto = new OverlayItem(posAct, null, null);
		CapaMyPos myPos = new CapaMyPos(iconMyPos, ClimbingGuideActivity.this, miPunto);
		mapa.getOverlays().add(myPos);
		mapa.postInvalidate();
	}

	//Metodo para action bar
	public class ExampleAction extends AbstractAction {

			public ExampleAction(int arg0) {
				super(arg0);
			}
	        @Override
	        public void performAction(View view) {
	    
	            Toast.makeText(ClimbingGuideActivity.this,"texto", Toast.LENGTH_SHORT).show();
	        }
	    }
	//Limpiar overlays
	private void borraOverlays(){
		List<Overlay> mapOverlays = mapa.getOverlays();
		if ((mapOverlays != null) && (mapOverlays.size() > 0)){
			for (Iterator<Overlay> i = mapOverlays.iterator(); i.hasNext();){
				i.next();
				i.remove();
			}
		}
	}
	
	//Borra el ultimo overlay de la lista
	private void borraUltimoOverlay(){
		List<Overlay> mapOverlays = mapa.getOverlays();
		Iterator<Overlay> i;
		Overlay o = null;
		if ((mapOverlays != null ) && (mapOverlays.size() > 0)){
			for  (i = mapOverlays.iterator(); i.hasNext();){
				o = i.next();
			}
			if (o.getClass().getName().contentEquals(CapaMyPos.class.getName()))
				i.remove();
		}
	}
	private void cargarPuntosMapa(Cursor c){		
		borraOverlays();
		if (c.getCount() > 0){
			ArrayList<SectorItem> puntos = new ArrayList<SectorItem>();
			Drawable icono = this.getResources().getDrawable(R.drawable.rock_climbing);
			String nombre;
			String grados;
			String xml = "";
			//String tipo = "";
			
			while (c.moveToNext()){
				nombre = c.getString(0);
				double inicX = c.getDouble(1);
				double inicY = c.getDouble(2);
				//double finX = c.getDouble(3);
				//double finY = c.getDouble(4);
				int numVias = c.getInt(5);
				grados = c.getString(6);
				//tipo = c.getString(7);
				xml = "";
				xml = c.getString(8);
				
		        GeoPoint punto = new GeoPoint((int) (inicX * 1E6), (int) (inicY * 1E6));
		        SectorItem sector = new SectorItem(punto, nombre, grados, numVias, xml);
		        //icono = setIcono(dist);
		        //icono.setBounds(0, 0, icono.getIntrinsicWidth(), icono.getIntrinsicHeight());
		        icono.setBounds(0-icono.getIntrinsicWidth() / 2, 0-icono.getIntrinsicHeight(), 
		        		icono.getIntrinsicWidth() / 2, 0);	//BoundCenterBottom
		        sector.setMarker(icono);
		        puntos.add(sector);
			}
			CapaSectores puntosMapa = new CapaSectores(icono,puntos, ClimbingGuideActivity.this, actionBar, mapa);
			mapa.getOverlays().add(puntosMapa);
		}
		else
			Toast.makeText(ClimbingGuideActivity.this, "Mapa vacio", Toast.LENGTH_SHORT).show();	
		mapa.postInvalidate();
		c.close();
		}

	private Drawable rotateIcon(float grados){
		
		Bitmap flechaBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.marker_04);
		//Crear bitmap blanco
		Bitmap canvasBitmap = flechaBitmap.copy(Bitmap.Config.ARGB_8888, true);
		canvasBitmap.eraseColor(0x00000000);
		Canvas lienzo = new Canvas(canvasBitmap);
		Matrix matriz = new Matrix();
		matriz.setRotate(grados, lienzo.getWidth()/2, (lienzo.getHeight()*60)/100 );
		lienzo.drawBitmap(flechaBitmap, matriz, null);
		return new BitmapDrawable(canvasBitmap);
	}
}